﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;


namespace xyPlot
{
    /// <summary>
    /// A simple container control to hold a single Graph control
    /// It also holds 3 buttons to control the graph
    /// 
    /// PanLeft : Paused the contained Graph, so will not accept any
    /// new live Stream values until the Graph is taken out of Pause mode.
    /// Will also pan back a viewable window (see App.Config) worth of values
    /// if there are enough previous values to show from the current point. 
    /// The viewable values are fetched from the database via some LINQ
    /// 
    /// Pause : Paused the contained Graph, so will not accept any
    /// new live Stream values until the Graph is taken out of Pause mode
    /// 
    /// 
    /// PanRight : Paused the contained Graph, so will not accept any
    /// new live Stream values until the Graph is taken out of Pause mode.
    /// Will also pan forward a viewable window (see App.Config) worth of values
    /// if there are enough future values to show from the current point. 
    /// The viewable values are fetched from the database via some LINQ
    /// 
    /// It should be noted that the PanLeft/PanRight functions are only available
    /// when the SUPPORTS_HISTORICAL_DATA setting is set to true, 
    /// see the Settings.settings file
    /// </summary>
    public partial class GraphTicker : UserControl
    {
        #region Data
        private Int32 SamplesWindowSize = 30;
        private Boolean SupportsHistoricalData = true;
        #endregion

        #region Ctor
        public GraphTicker()
        {
            InitializeComponent();
            this.DataContext = graph;
            this.Loaded += GraphTicker_Loaded;
        }

        #endregion

        #region DPs

        #region DataValues

        /// <summary>
        /// DataValues Dependency Property
        /// </summary>
        public static readonly DependencyProperty DataValuesProperty =
            DependencyProperty.Register("DataValues", 
            typeof(ThreadSafeObservableCollection<GraphDataItem>), typeof(GraphTicker),
                new FrameworkPropertyMetadata(
                        (ThreadSafeObservableCollection<GraphDataItem>)null,
                    new PropertyChangedCallback(OnDataValuesChanged)));

        /// <summary>
        /// Gets or sets the DataValues property.  
        /// </summary>
        public ThreadSafeObservableCollection<GraphDataItem> DataValues
        {
            get { return (ThreadSafeObservableCollection<GraphDataItem>)
                GetValue(DataValuesProperty); }
            set { SetValue(DataValuesProperty, value); }
        }

        /// <summary>
        /// Handles changes to the DataValues property.
        /// </summary>
        private static void OnDataValuesChanged(DependencyObject d, 
            DependencyPropertyChangedEventArgs e)
        {
            GraphTicker obj = (GraphTicker)d;
            if (e.NewValue != null)
            {
                obj.graph.DataValues = 
                    (ThreadSafeObservableCollection<GraphDataItem>)e.NewValue; ;
            }
        }
        #endregion

        #region GraphTitle

        /// <summary>
        /// GraphTitle Dependency Property
        /// </summary>
        public static readonly DependencyProperty GraphTitleProperty =
            DependencyProperty.Register("GraphTitle", typeof(String), typeof(GraphTicker),
                new FrameworkPropertyMetadata((String)String.Empty,
                    new PropertyChangedCallback(OnGraphTitleChanged)));

        /// <summary>
        /// Gets or sets the GraphTitle property.  
        /// </summary>
        public String GraphTitle
        {
            get { return (String)GetValue(GraphTitleProperty); }
            set { SetValue(GraphTitleProperty, value); }
        }

        /// <summary>
        /// Handles changes to the GraphTitle property.
        /// </summary>
        private static void OnGraphTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((GraphTicker)d).graph.GraphTitle = (String)e.NewValue;
        }
        #endregion

        #endregion

        #region Private Methods

        /// <summary>
        /// Works out whether to show the historical buttons or not
        /// based on the SUPPORTS_HISTORICAL_DATA Setting
        /// </summary>
        private void GraphTicker_Loaded(object sender, RoutedEventArgs e)
        {
            SupportsHistoricalData = 
                xyPlot.Properties.Settings.Default.SUPPORTS_HISTORICAL_DATA;

            BtnPanLeft.Visibility = SupportsHistoricalData ?
                Visibility.Visible : Visibility.Collapsed;

            BtnPanRight.Visibility = SupportsHistoricalData ?
                Visibility.Visible : Visibility.Collapsed;

        }

        /// <summary>
        /// Pauses the Graph, so will not accept any new live Stream values
        /// until the Graph is taken out of Pause mode. And also checks if current 
        /// 1st sequence number - total number of sample points in window &lt; 0. 
        /// And if this is ok, grabs a new window of points
        /// </summary>
        private void BtnPanLeft_Click(object sender, RoutedEventArgs e)
        {
        //    //Need to check if current 1st sequence number - total number of sample
        //    //points in window > 0

        //    graph.IsPaused = true;

        //    Double firstItemInWindowSequenceNumber = 
        //        DataValues.First().SampleSequenceNumber;

        //    SamplesWindowSize =
        //        xyPlot.Properties.Settings.Default.SAMPLE_WINDOW_SIZE;

        //    try
        //    {
        //        Double lowerLimitSequenceToFetch = firstItemInWindowSequenceNumber - 
        //            SamplesWindowSize;

        //        if (firstItemInWindowSequenceNumber - SamplesWindowSize > 0)
        //        {
        //            WPFTickerDataContext dataContext = new WPFTickerDataContext();
        //            //need to get the values from the DB
        //            //and ask graph to ObtainPointsForValues
        //            var dbReadSamples = 
        //                (from samples in dataContext.TickerSamples
        //                 where samples.SampleSequenceNumber >= 
        //                    lowerLimitSequenceToFetch &&
        //                 samples.SampleSequenceNumber < 
        //                    firstItemInWindowSequenceNumber
        //                 select samples);

        //            if (dbReadSamples.Count() > 0)
        //            {
        //                DataValues.Clear();
        //                foreach (var sample in dbReadSamples)
        //                {
        //                    DataValues.Add(new GraphDataItem
        //                    {
        //                        DataValue = sample.SampleValue,
        //                        SampleSequenceNumber = sample.SampleSequenceNumber,
        //                        TimeSampled = sample.SampleDate
        //                    });
        //                }
        //                graph.ObtainPointsForValues();

        //            }
        //            else
        //            {
        //                //if there are no values (there should be, but just to be safe)
        //                //accept new streaming live values if we cant pan to old ones
        //                graph.IsPaused = false;
        //            }
        //        }
        //    }
        //    catch
        //    {
        //        //if a database exception occurs with the LINQ to SQL stuff
        //        //there is not much we can do abouu, apart from start streaming the
        //        //current live values instead
        //        graph.IsPaused = false;
        //    }
        }



        ///// <summary>
        ///// Pauses the Graph, so will not accept any new live Stream values
        ///// until the Graph is taken out of Pause mode
        ///// </summary>
        private void BtnPauseResume_Click(object sender, RoutedEventArgs e)
        {
            graph.IsPaused = !graph.IsPaused;
        }

        ///// <summary>
        ///// Pauses the Graph, so will not accept any new live Stream values
        ///// until the Graph is taken out of Pause mode. And also checks if current
        ///// last sequence number + total number of sample points in window &lt; 
        ///// last item stored in the database. And if this is ok, grabs a new window
        ///// of points
        ///// </summary>
        private void BtnPanRight_Click(object sender, RoutedEventArgs e)
        {
        //    //Need to check if current last sequence number + total number of sample
        //    //points in window < last item stored

        //    graph.IsPaused = true;

        //    Double lastItemInWindowSequenceNumber = 
        //        DataValues.Last().SampleSequenceNumber;

        //    SamplesWindowSize =
        //        xyPlot.Properties.Settings.Default.SAMPLE_WINDOW_SIZE;

        //    try
        //    {
        //        Double uppLimitSequenceToFetch = lastItemInWindowSequenceNumber + 
        //            SamplesWindowSize;

        //        WPFTickerDataContext dataContext = new WPFTickerDataContext();

        //        var highestSequenceNumberStored = 
        //            (from samples in dataContext.TickerSamples
        //             select samples).Max(s => s.SampleSequenceNumber);

        //        if (lastItemInWindowSequenceNumber + SamplesWindowSize < 
        //            highestSequenceNumberStored)
        //        {
                    
        //            //need to get the values from the DB
        //            //and ask graph to ObtainPointsForValues
        //            var dbReadSamples = 
        //                (from samples in dataContext.TickerSamples
        //                 where samples.SampleSequenceNumber >= 
        //                    lastItemInWindowSequenceNumber &&
        //                 samples.SampleSequenceNumber < 
        //                    uppLimitSequenceToFetch
        //                 select samples);

        //            if (dbReadSamples.Count() > 0)
        //            {
        //                DataValues.Clear();
        //                foreach (var sample in dbReadSamples)
        //                {
        //                    DataValues.Add(new GraphDataItem
        //                    {
        //                        DataValue = sample.SampleValue,
        //                        SampleSequenceNumber = sample.SampleSequenceNumber,
        //                        TimeSampled = sample.SampleDate
        //                    });
        //                }
        //                graph.ObtainPointsForValues();
        //            }
        //            else
        //            {
        //                //if there are no values (there should be, but just to be safe)
        //                //accept new streaming live values if we cant pan to old ones
        //                graph.IsPaused = false;
        //            }
        //        }
        //    }
        //    catch
        //    {
        //        //if a database exception occurs with the LINQ to SQL stuff
        //        //there is not much we can do about, apart from start streaming the
        //        //current live values instead
        //        graph.IsPaused = false;
        //    }
        }
        #endregion
    }
}
